package org.example.demo1.service;

import org.example.demo1.dto.JaegerServiceMetricsDto;
import org.example.demo1.dto.NamespaceJaegerMetricsDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator; // 导入 Comparator
import java.util.HashMap; // 导入 HashMap
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; // 导入 Collectors

// 导入 Jackson 用于 JSON 解析
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Jaeger 监控服务类
 * 负责从 Jaeger API 获取数据并聚合为前端所需的指标
 */
@Service
@Slf4j
public class JaegerMonitorService {

    // 假设这个URL指向您的Jaeger Query服务 (例如：http://localhost:16686 或 http://${cluster.ip}:31245/jaeger)
    @Value("${monitor.jaeger.url}")
    private String jaegerQueryBaseUrl;

    // 如果您仍然想获取jaeger_query_requests_total，保留Prometheus URL
    @Value("${monitor.prometheus.url}")
    private String prometheusBaseUrl; // 保留但在此逻辑中未使用

    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper; // Jackson ObjectMapper

    public JaegerMonitorService(RestTemplate restTemplate, ObjectMapper objectMapper) {
        this.restTemplate = restTemplate;
        this.objectMapper = objectMapper;
        log.info("Jaeger Monitor Service initialized. Jaeger Query Base URL: {}", jaegerQueryBaseUrl);
    }

    /**
     * 获取 Jaeger 追踪概览指标，按命名空间分组
     * @return List<NamespaceJaegerMetricsDto> 包含每个命名空间下的 Jaeger 追踪指标
     */
    public List<NamespaceJaegerMetricsDto> getJaegerMetricsGroupedByNamespace() {
        log.info("从 Jaeger Query API 获取 Jaeger 指标（按命名空间分组）。");

        // 1. 获取所有服务列表
        List<String> fullServiceNames = getServiceNamesFromJaeger(); // 获取完整服务名称列表
        if (fullServiceNames.isEmpty()) {
            log.warn("未从 Jaeger API 获取到任何服务名称。");
            return Collections.singletonList(NamespaceJaegerMetricsDto.empty("default"));
        }

        // 使用 Map 来按命名空间分组数据
        Map<String, NamespaceJaegerMetricsDto> namespaceMetricsMap = new HashMap<>();

        // 2. 遍历每个完整服务名称，提取命名空间并获取追踪数据
        for (String fullServiceName : fullServiceNames) {
            String serviceDisplayName; // 用于前端显示的服务名（不含命名空间）
            String namespace;          // 提取出的命名空间

            int lastDotIndex = fullServiceName.lastIndexOf('.');
            if (lastDotIndex > 0 && lastDotIndex < fullServiceName.length() - 1) {
                // 假设服务名称格式为 "serviceName.namespace"
                serviceDisplayName = fullServiceName.substring(0, lastDotIndex);
                namespace = fullServiceName.substring(lastDotIndex + 1);
            } else {
                // 对于不含命名空间的名称（如 "jaeger-query"），将其归入 "system" 或 "default"
                serviceDisplayName = fullServiceName;
                // 您可以根据实际情况调整这里的默认命名空间，例如 "system" 或 "unclassified"
                namespace = "system"; // 或者 "default"
            }

            // 从 Map 中获取或创建对应的命名空间指标对象
            NamespaceJaegerMetricsDto namespaceMetrics = namespaceMetricsMap.computeIfAbsent(namespace, ns -> {
                NamespaceJaegerMetricsDto newNsMetrics = new NamespaceJaegerMetricsDto();
                newNsMetrics.setNamespace(ns);
                newNsMetrics.setLastUpdate(Instant.now());
                newNsMetrics.setExpanded(true); // 默认展开
                newNsMetrics.setServices(new ArrayList<>()); // 初始化服务列表
                return newNsMetrics;
            });

            try {
                // 设置查询时间范围：例如过去1小时的追踪 (转换为微秒)
                long endTimeUs = Instant.now().toEpochMilli() * 1000;
                long startTimeUs = Instant.now().minusSeconds(3600).toEpochMilli() * 1000; // 过去1小时

                // 调用 Jaeger API 获取追踪列表
                // 注意这里使用 fullServiceName 来查询 Jaeger API
                String tracesUrl = String.format("%s/api/traces?service=%s&start=%d&end=%d&limit=100",
                        jaegerQueryBaseUrl, fullServiceName, startTimeUs, endTimeUs);
                String jaegerResponse = restTemplate.getForObject(tracesUrl, String.class);

                // 解析追踪数据并统计
                JsonNode rootNode = objectMapper.readTree(jaegerResponse);
                JsonNode dataNode = rootNode.at("/data");

                long totalServiceTraces = 0;
                long errorServiceTraces = 0;
                List<Long> durations = new ArrayList<>(); // 用于存储每个追踪的持续时间（微秒）

                if (dataNode.isArray()) {
                    totalServiceTraces = dataNode.size(); // 每个元素是一个trace
                    for (JsonNode traceNode : dataNode) {
                        JsonNode spansNode = traceNode.at("/spans");
                        long traceDuration = 0; // 单个追踪的持续时间
                        boolean hasError = false;

                        if (spansNode.isArray() && !spansNode.isEmpty()) {
                            // 查找根span的持续时间作为追踪的持续时间
                            // 通常，Jaeger API 返回的追踪 JSON 中，root span是第一个没有 references 的 span
                            // 或者您可以简单地取所有 spans 中最大的 end time - 最小的 start time
                            // 这里我们采取查找根 span 的 duration
                            for (JsonNode spanNode : spansNode) {
                                // 如果 span 没有 references，通常是根 span
                                if (!spanNode.has("references") || spanNode.at("/references").isEmpty()) {
                                    if (spanNode.has("duration")) {
                                        traceDuration = spanNode.get("duration").asLong();
                                        break; // 找到根 span，跳出
                                    }
                                }
                            }

                            // 检查追踪中是否有任何一个 span 带有 error=true tag
                            for (JsonNode spanNode : spansNode) {
                                JsonNode tagsNode = spanNode.at("/tags");
                                if (tagsNode.isArray()) {
                                    for (JsonNode tag : tagsNode) {
                                        if ("error".equals(tag.at("/key").asText()) && tag.at("/value").asBoolean()) {
                                            hasError = true;
                                            break;
                                        }
                                    }
                                }
                                if (hasError) break; // 如果发现错误，就跳出当前span循环
                            }
                        }

                        if (traceDuration > 0) {
                            durations.add(traceDuration);
                        }
                        if (hasError) {
                            errorServiceTraces++;
                        }
                    }
                }

                // 计算平均耗时和 P99 耗时 (微秒转毫秒)
                long avgDuration = (long) (durations.stream().mapToLong(Long::longValue).average().orElse(0.0) / 1000);
                long p99Duration = calculateP99(durations) / 1000;

                // 构建服务指标DTO
                JaegerServiceMetricsDto serviceMetrics = new JaegerServiceMetricsDto();
                serviceMetrics.setServiceName(serviceDisplayName); // 使用提取出的显示名称
                serviceMetrics.setTotalTraces(totalServiceTraces);
                serviceMetrics.setErrorTraces(errorServiceTraces);
                serviceMetrics.setAvgDuration(avgDuration);
                serviceMetrics.setP99Duration(p99Duration);

                // 将服务指标添加到对应命名空间的列表中
                namespaceMetrics.getServices().add(serviceMetrics);
                // 累加到命名空间的总数
                namespaceMetrics.setTotalTracesInNamespace(namespaceMetrics.getTotalTracesInNamespace() + totalServiceTraces);
                namespaceMetrics.setErrorTracesInNamespace(namespaceMetrics.getErrorTracesInNamespace() + errorServiceTraces);

            } catch (Exception e) {
                log.error("从 Jaeger API 查询服务 '{}' 的追踪失败: {}", fullServiceName, e.getMessage());
                // 如果查询失败，为该服务添加一个默认/空指标，并归入相应命名空间
                JaegerServiceMetricsDto emptyServiceMetrics = new JaegerServiceMetricsDto(serviceDisplayName, 0, 0, 0, 0);
                namespaceMetrics.getServices().add(emptyServiceMetrics);
            }
        }

        // 最终返回所有命名空间的列表
        List<NamespaceJaegerMetricsDto> resultList = new ArrayList<>(namespaceMetricsMap.values());

        // 可选：对命名空间和服务进行排序，方便前端展示
        resultList.sort(Comparator.comparing(NamespaceJaegerMetricsDto::getNamespace));
        resultList.forEach(ns -> ns.getServices().sort(Comparator.comparing(JaegerServiceMetricsDto::getServiceName)));

        return resultList;
    }

    /**
     * 从 Jaeger Query API 获取所有服务名称
     * @return 服务名称列表
     */
    private List<String> getServiceNamesFromJaeger() {
        String servicesUrl = jaegerQueryBaseUrl + "/api/services";
        try {
            String jaegerResponse = restTemplate.getForObject(servicesUrl, String.class);
            JsonNode rootNode = objectMapper.readTree(jaegerResponse);
            JsonNode dataNode = rootNode.at("/data");
            if (dataNode.isArray()) {
                List<String> services = new ArrayList<>();
                for (JsonNode serviceNode : dataNode) {
                    services.add(serviceNode.asText());
                }
                return services;
            }
        } catch (Exception e) {
            log.error("从 Jaeger API 获取服务列表失败: {}", e.getMessage());
        }
        return Collections.emptyList();
    }

    /**
     * 计算 P99 耗时
     * @param durations 耗时列表（微秒）
     * @return P99 耗时（微秒）
     */
    private long calculateP99(List<Long> durations) {
        if (durations == null || durations.isEmpty()) {
            return 0;
        }
        Collections.sort(durations);
        int index = (int) Math.ceil(0.99 * durations.size()) - 1;
        if (index < 0) index = 0; // 确保索引不为负
        if (index >= durations.size()) index = durations.size() - 1; // 确保索引不越界
        return durations.get(index);
    }
}